package main

import (
	"fmt"
	"time"
)

var NUM int = 80000

// main
//
//	@Description:要求统计1~80000数字中，哪些是素数,素数放入resChannel中
func main() {
	getPrimeWithGoRouting() //212
	//getPrime()
}

// getPrime
//
//	@Description: 1~80000的素数
func getPrime() {
	start := time.Now().UnixMilli()
	var slice []int = make([]int, 0)
	for i := 1; i <= NUM; i++ {
		prime := isPrime(i)
		if prime {
			slice = append(slice, i)
		}
	}
	end := time.Now().UnixMilli()
	fmt.Println("耗时：", end-start) //2697
}

// getPrimeWithGoRouting
//
//	@Description: 1~80000的素数
func getPrimeWithGoRouting() {
	start := time.Now().UnixMilli()
	var goroutines int = 4
	dataChannel := make(chan int, NUM)
	resChannel := make(chan int, NUM)
	exitChannel := make(chan bool, goroutines)

	//开启一个协程，向dataChannel放入1~8000个数
	go putNum(dataChannel)

	//开启4个协程，从dataChannel取出数据，并判断是否为素数，如果是，就放入resChannel
	for i := 1; i <= goroutines; i++ {
		go primeNum(dataChannel, resChannel, exitChannel)
	}

	//[协程~匿名函数]当从exitChannel取出4个结果后，就可以关闭resChannel
	//go func() {
	//	for i := 0; i < goroutines; i++ {
	//		<-exitChannel
	//	}
	//	close(resChannel)
	//	close(exitChannel)
	//}()

	//同步的方式关闭resChannel
	for i := 0; i < goroutines; i++ {
		<-exitChannel
	}
	close(resChannel)
	close(exitChannel)

	//打印结果
	for v := range resChannel {
		fmt.Println("素数=", v)
	}
	fmt.Println("主函数退出~")
	end := time.Now().UnixMilli()
	fmt.Println("耗时：", end-start) //784
}

// putNum
//
//	@Description: 向dataChannel放入1~8000个数
//	@param dataChannel
func putNum(dataChannel chan int) {
	for i := 1; i <= NUM; i++ {
		dataChannel <- i
		//time.Sleep(time.Millisecond)
	}
	close(dataChannel)
}

// primeNum
//
//	@Description: 从dataChannel取出数据，并判断是否为素数，如果是，就放入resChannel
//	@param dataChannel
//	@param resChannel
//	@param exitChannel
func primeNum(dataChannel chan int, resChannel chan int, exitChannel chan bool) {
	for {
		num, ok := <-dataChannel
		if !ok {
			//取不到数据，就退出~
			break
		}
		if isPrime(num) {
			//是素数,放入结果channel
			resChannel <- num
		}
	}
	fmt.Println("取不到数据 exitChannel <- true")
	exitChannel <- true

}

// isPrime
//
//	@Description: 判断是否为素数
//	@param num
//	@return bool
func isPrime(num int) bool {
	var flag bool = true
	for i := 2; i < num; i++ {
		if num%i == 0 {
			flag = false
			break
		}
	}
	return flag
}
